package tt.dz.biz.dao.trade;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Repository;
import tt.dz.biz.dao.BaseDAO;
import tt.dz.vo.TranInfoVO;
import tt.dz.vo.TranSubVO;

@Repository("tradeDAO")
public class TradeDAOImpl
  extends BaseDAO
{
  private static final String INSERT_TRAN_INFO = "insert into ms_tran_info(trade_no,service_no,order_no,order_type,receiver,receiver_name,receiver_type,card_no,card_type,original_payer,original_payer_name,original_payer_type,payer,payer_name,payer_type,payment_amount,pay_type_code,channel_code,pay_state_code,cancle_status,check_account_sate,has_adjust,adjust_trade_no,related_order_no,reason,abstract_code,thd_pay_seq,thd_pay_amount,thd_poundage,thd_end_time,response_code,tran_time,receiver_balance,payer_balance,app_id,plat_time,accounting_date,check_account_date,batch_no,is_divided,account_state,start_account_time,end_account_time)  values(:tradeNo,:serviceNo,:orderNo,:orderType,:receiver,:receiverName,:receiverType,:cardNo,:cardType,:originalPayer,:originalPayerName,:originalPayerType,:payer,:payerName,:payerType,:paymentAmount,:payTypeCode,:channelCode,:payStateCode,:cancleStatus,:checkAccountSate,:hasAdjust,:adjustTradeNo,:relatedOrderNo,:reason,:abstractCode,:thdPaySeq,:thdPayAmount,:thdPoundage,:thdEndTime,:responseCode,:tranTime,:receiverBalance,:payerBalance,:appId,:platTime,:accountingDate,:checkAccountDate,:batchNo,:isDivided,:accountState,:startAccountTime,:endAccountTime )";
  private static final String INSERT_TRAN_INFO_JRNL = "insert into ms_tran_sub_jrnl(trade_no,sub_trade_no,service_no,is_cost,payer,payer_type,receiver,receiver_type,receiver_bal_type,receiver_name,receiver_is_self,payment_amount,cancle_status,check_account_sate,provider)  values(:tradeNo,:subTradeNo,:serviceNo,:isCost,:payer,:payerType,:receiver,:receiverType,:receiverBalType,:receiverName,:receiverIsSelf,:paymentAmount,:cancleStatus,:checkAccountSate,:provider )";
  private static final String UPDATE_BATCH_PAYED = "update ms_tran_info  set pay_state_code = :payStateCode  where payer=:payer  and receiver=:receiver  and batch_no = :batchNo  and service_no=:serviceNo  and pay_type_code in (2,3) ";
  private static final String QUERY_ALL_TRAN_INFO = "select t1.trade_no as tradeNo,t1.service_no as mainService,t1.receiver as mainReceiverNo,t1.payment_amount as mainPaymentAmount,t1.card_no as cardNo,t1.pay_type_code as payTypeCode,t1.channel_code as channelCode,t1.has_adjust as hasAdjust,t1.account_state as accountState,t1.plat_time platTime,t2.sub_trade_no as subTradeNo,t2.service_no subServiceNo,t2.receiver subReceiverNo,t2.payment_amount subPaymentAmount,t3.channel_name as channelName from ms_tran_info t1 left join ms_tran_sub_jrnl t2 on t1.trade_no = t2.trade_no left join ms_pay_channel t3 on t1.channel_code = t3.channel_code where 1 = 1 ";
  
  public int insertTranInfo(TranInfoVO aObj)
  {
    return save("insert into ms_tran_info(trade_no,service_no,order_no,order_type,receiver,receiver_name,receiver_type,card_no,card_type,original_payer,original_payer_name,original_payer_type,payer,payer_name,payer_type,payment_amount,pay_type_code,channel_code,pay_state_code,cancle_status,check_account_sate,has_adjust,adjust_trade_no,related_order_no,reason,abstract_code,thd_pay_seq,thd_pay_amount,thd_poundage,thd_end_time,response_code,tran_time,receiver_balance,payer_balance,app_id,plat_time,accounting_date,check_account_date,batch_no,is_divided,account_state,start_account_time,end_account_time)  values(:tradeNo,:serviceNo,:orderNo,:orderType,:receiver,:receiverName,:receiverType,:cardNo,:cardType,:originalPayer,:originalPayerName,:originalPayerType,:payer,:payerName,:payerType,:paymentAmount,:payTypeCode,:channelCode,:payStateCode,:cancleStatus,:checkAccountSate,:hasAdjust,:adjustTradeNo,:relatedOrderNo,:reason,:abstractCode,:thdPaySeq,:thdPayAmount,:thdPoundage,:thdEndTime,:responseCode,:tranTime,:receiverBalance,:payerBalance,:appId,:platTime,:accountingDate,:checkAccountDate,:batchNo,:isDivided,:accountState,:startAccountTime,:endAccountTime )", aObj);
  }
  
  public int insertTranSubInfo(TranSubVO aObj)
  {
    return save("insert into ms_tran_sub_jrnl(trade_no,sub_trade_no,service_no,is_cost,payer,payer_type,receiver,receiver_type,receiver_bal_type,receiver_name,receiver_is_self,payment_amount,cancle_status,check_account_sate,provider)  values(:tradeNo,:subTradeNo,:serviceNo,:isCost,:payer,:payerType,:receiver,:receiverType,:receiverBalType,:receiverName,:receiverIsSelf,:paymentAmount,:cancleStatus,:checkAccountSate,:provider )", aObj);
  }
  
  public int[] batchInsertTranSubInfo(List<TranSubVO> tranSubVOList)
  {
    return batchSave("insert into ms_tran_sub_jrnl(trade_no,sub_trade_no,service_no,is_cost,payer,payer_type,receiver,receiver_type,receiver_bal_type,receiver_name,receiver_is_self,payment_amount,cancle_status,check_account_sate,provider)  values(:tradeNo,:subTradeNo,:serviceNo,:isCost,:payer,:payerType,:receiver,:receiverType,:receiverBalType,:receiverName,:receiverIsSelf,:paymentAmount,:cancleStatus,:checkAccountSate,:provider )", tranSubVOList);
  }
  
  public int updateBatchPayed(TranInfoVO aObj)
  {
    return save("update ms_tran_info  set pay_state_code = :payStateCode  where payer=:payer  and receiver=:receiver  and batch_no = :batchNo  and service_no=:serviceNo  and pay_type_code in (2,3) ", aObj);
  }
  
  public List<TranInfoVO> queryTranInfo(TranInfoVO tranInfoVO)
  {
    List<Map<String, Object>> datas = null;
    List<TranInfoVO> ret = new ArrayList();
    TranInfoVO tempTranInfoVO = null;
    String tradeNo = null;
    String subTradeNo = null;
    TranInfoVO existTranInfoVO = null;
    
    StringBuffer sb = new StringBuffer("select t1.trade_no as tradeNo,t1.service_no as mainService,t1.receiver as mainReceiverNo,t1.payment_amount as mainPaymentAmount,t1.card_no as cardNo,t1.pay_type_code as payTypeCode,t1.channel_code as channelCode,t1.has_adjust as hasAdjust,t1.account_state as accountState,t1.plat_time platTime,t2.sub_trade_no as subTradeNo,t2.service_no subServiceNo,t2.receiver subReceiverNo,t2.payment_amount subPaymentAmount,t3.channel_name as channelName from ms_tran_info t1 left join ms_tran_sub_jrnl t2 on t1.trade_no = t2.trade_no left join ms_pay_channel t3 on t1.channel_code = t3.channel_code where 1 = 1 ");
    if ((tranInfoVO.getCardNo() != null) && 
      (!tranInfoVO.getCardNo().trim().equals(""))) {
      sb.append("and t1.card_no=:cardNo ");
    }
    if ((tranInfoVO.getServiceNo() != null) && 
      (!"".equals(tranInfoVO.getServiceNo().trim()))) {
      sb.append("and t1.service_no=:serviceNo ");
    }
    if (tranInfoVO.getStartDate() != null) {
      sb.append("and t1.plat_time >= :startDate ");
    }
    if (tranInfoVO.getEndDate() != null) {
      sb.append("and t1.plat_time <= :endDate ");
    }
    datas = queryForList(sb.toString(), tranInfoVO);
    for (Map<String, Object> row : datas)
    {
      tradeNo = (String)row.get("tradeNo");
      subTradeNo = (String)row.get("subTradeNo");
      
      existTranInfoVO = findTranInfoVOInRetList(tradeNo, ret);
      if (existTranInfoVO != null)
      {
        if (subTradeNo != null) {
          existTranInfoVO.getTranSubVOList().add(packageSubTranInfo(row));
        }
      }
      else
      {
        tempTranInfoVO = new TranInfoVO();
        tempTranInfoVO.setTradeNo(tradeNo);
        tempTranInfoVO.setServiceNo((String)row.get("mainService"));
        tempTranInfoVO.setReceiver((String)row.get("mainReceiverNo"));
        tempTranInfoVO.setPaymentAmount((BigDecimal)row.get("mainPaymentAmount"));
        tempTranInfoVO.setCardNo((String)row.get("cardNo"));
        tempTranInfoVO.setPayTypeCode((Integer)row.get("payTypeCode"));
        tempTranInfoVO.setChannelCode((String)row.get("channelCode"));
        tempTranInfoVO.setChannelName((String)row.get("channelName"));
        tempTranInfoVO.setHasAdjust((Integer)row.get("hasAdjust"));
        tempTranInfoVO.setAccountState((Integer)row.get("accountState"));
        tempTranInfoVO.setPlatTime((Date)row.get("platTime"));
        if (subTradeNo != null) {
          tempTranInfoVO.getTranSubVOList().add(packageSubTranInfo(row));
        }
        ret.add(tempTranInfoVO);
      }
    }
    return ret;
  }
  
  private TranInfoVO findTranInfoVOInRetList(String tradeNo, List<TranInfoVO> tranInfos)
  {
    for (TranInfoVO temp : tranInfos) {
      if (tradeNo.equals(temp.getTradeNo())) {
        return temp;
      }
    }
    return null;
  }
  
  private TranSubVO packageSubTranInfo(Map<String, Object> row)
  {
    TranSubVO tranSubVO = new TranSubVO();
    
    tranSubVO.setServiceNo((String)row.get("subServiceNo"));
    tranSubVO.setReceiver((String)row.get("subReceiverNo"));
    tranSubVO.setPaymentAmount((BigDecimal)row.get("subPaymentAmount"));
    
    return tranSubVO;
  }
}
